package com.softa.common.sysconfig.mvc;

import com.softa.common.constant.Constants;
import com.softa.common.sysconfig.exception.BusinessException;
import com.softa.common.sysconfig.exception.UnAuthorizedException;
import com.softa.common.sysconfig.support.HttpCode;
import com.softa.common.sysconfig.support.Result;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.http.HttpStatus;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.io.IOException;
import java.util.List;
import java.util.Set;

/**
 * Created by yangl on 2018/5/7.
 */
@ControllerAdvice
public class ExceptionHandlerAdvice {

    /**
     * 没有权限 异常
     * <p/>
     * 后续根据不同的需求定制即可
     */
    @ExceptionHandler({UnauthorizedException.class})
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ModelAndView processUnauthenticatedException(NativeWebRequest request, UnauthorizedException e) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("exception", e);
        mv.setViewName("unauthorized");
        return mv;
    }

    @ExceptionHandler(BindException.class)
    @ResponseBody
    public Result bindExceptionHandler(BindException ex,
                                            HttpServletResponse response, HttpServletRequest request) throws IOException {
        response.setStatus(HttpCode.BAD_REQUEST.value());
        BindingResult result = ex.getBindingResult();
        List<FieldError> fieldErrorList = result.getFieldErrors();
        StringBuilder sb = new StringBuilder();
        for(FieldError fieldError : fieldErrorList){
            String field = fieldError.getField();
            if(sb.length() == 0){
                sb.append(field+"："+fieldError.getDefaultMessage());
            }else{
                sb.append(","+field+"："+fieldError.getDefaultMessage());
            }
        }
        String message = sb.toString();
        return new Result(HttpCode.BAD_REQUEST.value(),message);
    }

    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public Result businessExceptionHandler(BusinessException ex,
                                           HttpServletResponse response, HttpServletRequest request) throws IOException {
        ModelMap map = new ModelMap();
        ex.handler(map);
        String message = map.get(Constants.EXCEPTION_MSG) == null ? null : map.get(Constants.EXCEPTION_MSG).toString();
        Integer code = Integer.parseInt(map.get(Constants.EXCEPTION_CODE).toString());
        Integer msgCode = map.get(Constants.EXCEPTION_MSGCODE) == null ? null : Integer.parseInt(map.get(Constants.EXCEPTION_MSGCODE).toString());
        return new Result(code, msgCode, message);
    }

    @ExceptionHandler(UnAuthorizedException.class)
    @ResponseBody
    public Result UnAuthorizedExceptionHandler(UnAuthorizedException ex,
                                           HttpServletResponse response, HttpServletRequest request) throws IOException {
        ModelMap map = new ModelMap();
        ex.handler(map);
        String message = map.get(Constants.EXCEPTION_MSG) == null ? null : map.get(Constants.EXCEPTION_MSG).toString();
        Integer code = Integer.parseInt(map.get(Constants.EXCEPTION_CODE).toString());
        Integer msgCode = map.get(Constants.EXCEPTION_MSGCODE) == null ? null : Integer.parseInt(map.get(Constants.EXCEPTION_MSGCODE).toString());
        return new Result(code, msgCode, message);
    }

    @ExceptionHandler(Exception.class)
//    @ResponseBody
    public void exceptionHandler(Exception ex, HttpServletResponse response, HttpServletRequest request)
            throws IOException {
//        response.setStatus(HttpCode.INTERNAL_SERVER_ERROR.value());
//        return new Result(HttpCode.INTERNAL_SERVER_ERROR.value(), ex.getMessage());
        ex.printStackTrace();
    }

}
